//
// Created by yycs0 on 25-2-11.
//

#include <algorithm>
#include <unordered_set>
#include "PushBoxGame.h"

int getCost(const PathState &pathstate, const MapInfo& mapInfo, const std::vector<std::vector<char>>& grid)
{
    int cost = 0;
    for(const auto& i : pathstate.actions)
    {
        if(i.type > -1)cost ++;
    }
    //return cost + pathstate.actions.size();
    int pcost = INT_MAX;
    for(int i = 0; i < pathstate.state.boxx.size(); ++i)
    {
        int minDis = INT_MAX;
        for(int j = 0; j < mapInfo.targets.size(); ++j)
        {
            if(minDis > std::abs(pathstate.state.boxx[i]-mapInfo.targets[j].x)+std::abs(pathstate.state.boxy[i]-mapInfo.targets[j].y))
            {
                minDis = std::abs(pathstate.state.boxx[i]-mapInfo.targets[j].x)+std::abs(pathstate.state.boxy[i]-mapInfo.targets[j].y);
            }
        }
        if(pcost > std::abs(pathstate.state.boxx[i]-pathstate.state.px)+std::abs(pathstate.state.boxy[i]-pathstate.state.py))
        {
            pcost = std::abs(pathstate.state.boxx[i]-pathstate.state.px)+std::abs(pathstate.state.boxy[i]-pathstate.state.py);
        }
        cost += minDis;
    }
    return cost + pathstate.actions.size() + pcost;
}

struct Compare {
    const std::vector<std::vector<char>>& grid;
    const MapInfo& mapInfo;
    Compare(const std::vector<std::vector<char>>& grid_, const MapInfo& mapInfo_):grid(grid_),mapInfo(mapInfo_){}
    bool operator()(const PathState& a, const PathState& b) const {
        return getCost(a, mapInfo, grid) > getCost(b,mapInfo, grid);
    }
};

// B Box
// S Person
// T Target
// . Floor
// # Wall
// A Box on Target
// C Person on Target

// 判断箱子是否被卡住
// LeftUp, LeftDown, RightUp, RightDown
static int dx1Tab[] = {-1 ,-1,  1,  1};
static int dy1Tab[] = { 0 , 0,  0,  0};
static int dx2Tab[] = { 0 , 0,  0,  0};
static int dy2Tab[] = {-1 , 1, -1,  1};
std::vector<std::vector<char>> getMap(const std::vector<std::vector<char>>& ingrid, State& info, MapInfo& mapInfo)
{
    std::vector<std::vector<char>> grid;
    info.boxx.clear();
    info.boxy.clear();
    mapInfo.targets.clear();
    mapInfo.blockPosx.clear();
    mapInfo.blockPosy.clear();
    grid.insert(grid.end(), ingrid.begin(), ingrid.end());
    int yMin = grid.size()-1;
    int yMax = 0;
    int xMin = grid[0].size()-1;
    int xMax = 0;
    for(int i = 0; i < grid.size(); ++i)
    {
        for(int j = 0; j < grid[i].size(); ++j)
        {
            if(grid[i][j] == 'B')
            {
                grid[i][j] = '.';
                info.boxx.emplace_back(j);
                info.boxy.emplace_back(i);
            }
            if(grid[i][j] == 'S')
            {
                grid[i][j] = '.';
                info.px = j;
                info.py = i;
            }
            if(grid[i][j] == 'T')
            {
                Target target{};
                target.x = j;
                target.y = i;
                mapInfo.targets.emplace_back(target);
            }
            if(grid[i][j] == 'A')
            {
                grid[i][j] = 'T';
                info.boxx.emplace_back(j);
                info.boxy.emplace_back(i);
                Target target{};
                target.x = j;
                target.y = i;
                mapInfo.targets.emplace_back(target);
            }
            if(grid[i][j] == 'C')
            {
                grid[i][j] = 'T';
                info.px = j;
                info.py = i;
                Target target{};
                target.x = j;
                target.y = i;
                mapInfo.targets.emplace_back(target);
            }
            if(grid[i][j] != '#')
            {
                if(yMin > i)yMin = i;
                if(yMax < i)yMax = i;
                if(xMin > j)xMin = j;
                if(xMax < j)xMax = j;
            }
        }
    }
    mapInfo.yMin = yMin;
    mapInfo.yMax = yMax;
    mapInfo.xMin = xMin;
    mapInfo.xMax = xMax;
    int yMinTgts = 0;
    int yMaxTgts = 0;
    int xMinTgts = 0;
    int xMaxTgts = 0;
    for(int i = 0; i < mapInfo.targets.size(); ++i)
    {
        if(mapInfo.targets[i].y <= yMin)yMinTgts++;
        if(mapInfo.targets[i].y >= yMax)yMaxTgts++;
        if(mapInfo.targets[i].x <= xMin)xMinTgts++;
        if(mapInfo.targets[i].x >= xMax)xMaxTgts++;
    }
//    std::cout<<"yMin: "<<yMin<<std::endl;
//    std::cout<<"yMax: "<<yMax<<std::endl;
//    std::cout<<"xMin: "<<xMin<<std::endl;
//    std::cout<<"xMax: "<<xMax<<std::endl;
//    std::cout<<"yMinTgts: "<<yMinTgts<<std::endl;
//    std::cout<<"yMaxTgts: "<<yMaxTgts<<std::endl;
//    std::cout<<"xMinTgts: "<<xMinTgts<<std::endl;
//    std::cout<<"xMaxTgts: "<<xMaxTgts<<std::endl;
    mapInfo.yMinTgts = yMinTgts;
    mapInfo.yMaxTgts = yMaxTgts;
    mapInfo.xMinTgts = xMinTgts;
    mapInfo.xMaxTgts = xMaxTgts;
    for(int i = 0; i < grid.size(); ++i)
    {
        for(int j = 0; j < grid[i].size(); ++j)
        {
            bool isBlock = false;
            if(grid[i][j] == '.')
            {
                for(int k = 0; k < 4; ++k)
                {
                    int pos1x = j + dx1Tab[k];
                    int pos1y = i + dy1Tab[k];
                    int pos2x = j + dx2Tab[k];
                    int pos2y = i + dy2Tab[k];
                    bool pos1valid = true;
                    bool pos2valid = true;
                    if(pos1x < 0 || pos1x >= grid[0].size() || pos1y < 0 || pos1y >= grid.size())
                    {
                        pos1valid = false;
                    }else{
                        if(grid[pos1y][pos1x] == '#')
                        {
                            pos1valid = false;
                        }
                    }
                    if(pos2x < 0 || pos2x >= grid[0].size() || pos2y < 0 || pos2y >= grid.size())
                    {
                        pos2valid = false;
                    }
                    else{
                        if(grid[pos2y][pos2x] == '#')
                        {
                            pos2valid = false;
                        }
                    }
                    if((!pos1valid) && (!pos2valid))
                    {
                        isBlock = true;
                        break;
                    }
                }
            }
            if(isBlock)
            {
                mapInfo.blockPosx.emplace_back(j);
                mapInfo.blockPosy.emplace_back(i);
                //std::cout<<"blockPos: "<<j<<","<<i<<std::endl;
            }
        }
    }
    return grid;
}

bool isAction(Action &action, const State &cur_state, std::vector<std::vector<char>>& grid)
{
    int npx = cur_state.px + action.dx;
    int npy = cur_state.py + action.dy;
    int nboxx = cur_state.px + 2*action.dx;
    int nboxy = cur_state.py + 2*action.dy;
//    if(npy < 0 || npy >= grid.size())
//    {
//        return false;
//    }
//    if(npx < 0 || npx >= grid[npy].size())
//    {
//        return false;
//    }
    if(grid[npy][npx] == '#')
    {
        //下一步是墙
        return false;
    }
    for(int i = 0; i < cur_state.boxx.size(); ++i)
    {
        if((grid[npy][npx] == '.'||grid[npy][npx] == 'T')&& npx == cur_state.boxx[i] && npy == cur_state.boxy[i])
        {
            //下一步是箱子
            action.type = i;
//            if(nboxy < 0 || nboxy >= grid.size())
//            {
//                return false;
//            }
//            if(nboxx < 0 || nboxx >= grid[nboxy].size())
//            {
//                return false;
//            }
            if(grid[nboxy][nboxx] == '#')
            {
                return false;
            }
            //下下步还是箱子
            for(int j = 0; j < cur_state.boxx.size(); ++j)
            {
                if(nboxx == cur_state.boxx[j] && nboxy == cur_state.boxy[j])
                {
                    return false;
                }
            }
        }
    }
    return true;
}
State move(const Action& action, const State &cur_state, std::vector<std::vector<char>>& grid)
{
    State new_state = cur_state;
    new_state.px = cur_state.px + action.dx;
    new_state.py = cur_state.py + action.dy;
    if(action.type > -1)
    {
        new_state.boxx[action.type] = cur_state.px + 2*action.dx;
        new_state.boxy[action.type] = cur_state.py + 2*action.dy;
    }
    return new_state;
}

static int dxTab[] = {1 ,-1, 0,  0};
static int dyTab[] = {0 , 0, 1, -1};
std::vector<ActionState> get_successor(const State &cur_state, std::vector<std::vector<char>>& grid)
{
    std::vector<ActionState> ASList;
    for(int i = 0; i < 4; ++i)
    {
        ActionState actionState{};
        actionState.action.type = -1;
        actionState.action.dx = dxTab[i];
        actionState.action.dy = dyTab[i];
        if(isAction(actionState.action, cur_state, grid))
        {
            actionState.state  = move(actionState.action, cur_state, grid);
            ASList.emplace_back(actionState);
        }
    }
    return ASList;
}
// 自定义哈希函数
struct VectorHash {
    std::size_t operator()(const std::vector<long>& v) const {
        std::size_t seed = v.size();
        for (long i : v) {
            // 使用 std::hash 对每个元素进行哈希，并结合到种子中
            seed ^= std::hash<long>()(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        }
        return seed;
    }
};
// 自定义相等比较函数
struct VectorEqual {
    bool operator()(const std::vector<long>& a, const std::vector<long>& b) const {
        return a == b;
    }
};
bool boxBlock1(const State& state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo);
bool boxBlock2(const State& state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo);
bool boxBlock3(const State& state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo);
bool isRight(const State& cur_state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo)
{
    bool alltarget = true;
    for(int i = 0; i < cur_state.boxx.size(); ++i)
    {
        if(grid[cur_state.boxy[i]][cur_state.boxx[i]] != 'T')
        {
            alltarget = false;
            break;
        }
    }
    return alltarget;
}
std::vector<Action> SolvePushBox(const State& state, std::vector<std::vector<char>>& grid,const MapInfo& mapInfo) {
    PathState pathState;
    pathState.state = state;
    Compare compare(grid, mapInfo);
    std::priority_queue<PathState, std::vector<PathState>, Compare> openlist(compare);
    std::unordered_set<std::vector<long>,VectorHash,VectorEqual> closelist;
    openlist.push(pathState);
    while(!openlist.empty())
    {
        PathState cur_state = openlist.top();
        openlist.pop();
        //std::cout<<"current state px: "<<cur_state.state.px<<","<<cur_state.state.py<<std::endl;
        //std::cout<<"current state box: "<<std::endl;
        //for(int i = 0; i < cur_state.state.boxx.size(); ++i)
        //{
        //    std::cout<<"    "<<cur_state.state.boxx[i]<<","<<cur_state.state.boxy[i]<<std::endl;
        //}

        if(isRight(cur_state.state, grid, mapInfo))
        {
            return cur_state.actions;
        }
        if(boxBlock1(cur_state.state, grid, mapInfo))
        {
            continue;
        }
        if(boxBlock3(cur_state.state, grid, mapInfo))
        {
            continue;
        }
        if(boxBlock2(cur_state.state, grid, mapInfo))
        {
            continue;
        }
        auto succs = get_successor(cur_state.state, grid);
        for(const auto& succ : succs)
        {
            PathState next_state = cur_state;
            next_state.state = move(succ.action, cur_state.state, grid);
            next_state.actions.emplace_back(succ.action);

            std::vector<long> hashlist;
            for(int i = 0; i < next_state.state.boxx.size(); ++i)
            {
                //long hash = next_state.state.boxx[i]*1000000 + next_state.state.boxy[i]*10000 + next_state.state.px*100 + next_state.state.py;
                long hash = next_state.state.boxx[i]*20 + next_state.state.boxy[i];
                hashlist.emplace_back(hash);
            }
            std::sort(hashlist.begin(), hashlist.end());
            hashlist.emplace_back(next_state.state.px*20 + next_state.state.py);
            if(closelist.find(hashlist) == closelist.end())
            {
                closelist.insert(hashlist);
                openlist.push(next_state);
            }
        }
    }
    return std::vector<Action>{};
}

bool boxBlock1(const State& state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo) {
    for(int i = 0; i < state.boxx.size(); ++i) {
        for(int j = 0; j < mapInfo.blockPosx.size(); ++j)
        {
            if(state.boxx[i] == mapInfo.blockPosx[j] && state.boxy[i] == mapInfo.blockPosy[j])
            {
                return true;
            }
        }
    }
    return false;
}
bool boxBlock4(const State& state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo) {
    for(int i = 0; i < state.boxx.size(); ++i) {
        for(int j = 0; j < 4; ++j)
        {
            int pos1x = state.boxx[i] + dx1Tab[j];
            int pos1y = state.boxy[i] + dy1Tab[j];
            int pos2x = state.boxx[i] + dx2Tab[j];
            int pos2y = state.boxy[i] + dy2Tab[j];
            bool pos1valid = true;
            bool pos2valid = true;
            if(pos1x < 0 || pos1x >= grid[0].size() || pos1y < 0 || pos1y >= grid.size())
            {
                pos1valid = false;
            }else{
                if(grid[pos1y][pos1x] == '#')
                {
                    pos1valid = false;
                }
            }
            if(pos2x < 0 || pos2x >= grid[0].size() || pos2y < 0 || pos2y >= grid.size())
            {
                pos2valid = false;
            }else{
                if(grid[pos2y][pos2x] == '#')
                {
                    pos2valid = false;
                }
            }
            if((!pos1valid) && (!pos2valid))
            {
//                std::cout<<"Box is Block"<<state.boxx[i]<<state.boxy[i]<<std::endl;
//                std::cout<<"Cannot Move to: "<<pos1x<<","<<pos1y<<std::endl;
//                std::cout<<"Cannot Move to: "<<pos2x<<","<<pos2y<<std::endl;
//                std::cout<<"Person: "<<state.px<<","<<state.py<<std::endl;
//                std::cout<<"Box: ";
//                for(int idx = 0; idx < state.boxx.size(); ++idx){
//                    std::cout<<state.boxx[idx]<<","<<state.boxy[idx]<<std::endl;
//                }
                if(grid[state.boxy[i]][state.boxx[i]] != 'T'){
                    return true;
                }
            }
        }
    }
    return false;
}

bool boxBlock2(const State& state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo) {
    int boxInxMin = 0;
    int boxInxMax = 0;
    int boxInyMin = 0;
    int boxInyMax = 0;
    for(int i = 0; i < state.boxx.size(); ++i) {
        if(state.boxx[i] <= mapInfo.xMin)boxInxMin++;
        if(state.boxx[i] >= mapInfo.xMax)boxInxMax++;
        if(state.boxy[i] <= mapInfo.yMin)boxInyMin++;
        if(state.boxy[i] >= mapInfo.yMax)boxInyMax++;
    }
    if(boxInxMin > mapInfo.xMinTgts || boxInxMax > mapInfo.xMaxTgts || boxInyMin > mapInfo.yMinTgts || boxInyMax > mapInfo.yMaxTgts)
    {
//        std::cout<<"Box is Block2"<<std::endl;
//        if(boxInxMin > mapInfo.xMinTgts) std::cout<<"boxInxMin > mapInfo.xMinTgts"<<boxInxMin<<""<<mapInfo.xMinTgts<<std::endl;
//        if(boxInxMax > mapInfo.xMaxTgts) std::cout<<"boxInxMax > mapInfo.xMaxTgts"<<boxInxMax<<""<<mapInfo.xMaxTgts<<std::endl;
//        if(boxInyMin > mapInfo.yMinTgts) std::cout<<"boxInyMin > mapInfo.yMinTgts"<<boxInyMin<<""<<mapInfo.yMinTgts<<std::endl;
//        if(boxInyMax > mapInfo.yMaxTgts) std::cout<<"boxInyMax > mapInfo.yMaxTgts"<<boxInyMax<<""<<mapInfo.yMaxTgts<<std::endl;
//        std::cout<<"Box: ";
//        for(int idx = 0; idx < state.boxx.size(); ++idx){
//            std::cout<<state.boxx[idx]<<","<<state.boxy[idx]<<std::endl;
//        }
        return true;
    }
    return false;
}
bool boxBlock3(const State& state, const std::vector<std::vector<char>> &grid, const MapInfo& mapInfo)
{
    for(int i = 0; i < state.boxx.size(); ++i)
    {
        for(int j = 0; j < state.boxx.size(); ++j)
        {
            if(i != j)
            {
                int boxdx = state.boxx[i]- state.boxx[j];
                int boxdy = state.boxy[i]- state.boxy[j];
                if(boxdx == 0 &&(boxdy == 1 || boxdy == -1))
                {
                    // 2个箱子竖着相邻
                    int leftix  = state.boxx[i]-1;
                    int leftiy  = state.boxy[i];
                    int leftjx  = state.boxx[j]-1;
                    int leftjy  = state.boxy[j];
                    bool iIsValid = true;
                    bool jIsValid = true;
                    if(leftix < 0 || leftix >= grid[0].size() || leftiy < 0 || leftiy >= grid.size())
                    {
                        iIsValid = false;
                    }else{
                        if(grid[leftiy][leftix] == '#')
                        {
                            iIsValid = false;
                        }
                    }
                    if(leftjx < 0 || leftjx >= grid[0].size() || leftjy < 0 || leftjy >= grid.size())
                    {
                        jIsValid = false;
                    }else{
                        if(grid[leftjy][leftjx] == '#')
                        {
                            jIsValid = false;
                        }
                    }
                    if((!iIsValid)&&(!jIsValid)&&((grid[state.boxy[i]][state.boxx[i]]!= 'T')||(grid[state.boxy[j]][state.boxx[j]]!= 'T')))
                    {
                        //std::cout<<"Box is Block3"<<state.boxx[i]<<","<<state.boxy[i]<<"--"<<state.boxx[j]<<","<<state.boxy[j]<<std::endl;
                        //std::cout<<"Box: ";
                        //for(int idx = 0; idx < state.boxx.size(); ++idx){
                        //    std::cout<<state.boxx[idx]<<","<<state.boxy[idx]<<std::endl;
                        //}
                        return true;
                    }
                    int rightix = state.boxx[i]+1;
                    int rightiy = state.boxy[i];
                    int rightjx = state.boxx[j]+1;
                    int rightjy = state.boxy[j];
                    iIsValid = true;
                    jIsValid = true;
                    if(rightix < 0 || rightix >= grid[0].size() || rightiy < 0 || rightiy >= grid.size())
                    {
                        iIsValid = false;
                    }else{
                        if(grid[rightiy][rightix] == '#')
                        {
                            iIsValid = false;
                        }
                    }
                    if(rightjx < 0 || rightjx >= grid[0].size() || rightjy < 0 || rightjy >= grid.size())
                    {
                        jIsValid = false;
                    }else{
                        if(grid[rightjy][rightjx] == '#')
                        {
                            jIsValid = false;
                        }
                    }
                    if((!iIsValid)&&(!jIsValid)&&((grid[state.boxy[i]][state.boxx[i]]!= 'T')||(grid[state.boxy[j]][state.boxx[j]]!= 'T')))
                    {
                        //std::cout<<"Box is Block3"<<state.boxx[i]<<","<<state.boxy[i]<<"--"<<state.boxx[j]<<","<<state.boxy[j]<<std::endl;
                        //std::cout<<"Box: ";
                        //for(int idx = 0; idx < state.boxx.size(); ++idx){
                        //    std::cout<<state.boxx[idx]<<","<<state.boxy[idx]<<std::endl;
                        //}
                        return true;
                    }
                }

                if((boxdx == 1||boxdx == -1) &&(boxdy == 0))
                {
                    // 2个箱子横着相邻
                    int upix  = state.boxx[i];
                    int upiy  = state.boxy[i]-1;
                    int upjx  = state.boxx[j];
                    int upjy  = state.boxy[j]-1;
                    bool iIsValid = true;
                    bool jIsValid = true;
                    if(upix < 0 || upix >= grid[0].size() || upiy < 0 || upiy >= grid.size())
                    {
                        iIsValid = false;
                    }else{
                        if(grid[upiy][upix] == '#')
                        {
                            iIsValid = false;
                        }
                    }
                    if(upjx < 0 || upjx >= grid[0].size() || upjy < 0 || upjy >= grid.size())
                    {
                        jIsValid = false;
                    }else{
                        if(grid[upjy][upjx] == '#')
                        {
                            jIsValid = false;
                        }
                    }
                    if((!iIsValid)&&(!jIsValid)&&((grid[state.boxy[i]][state.boxx[i]]!= 'T')||(grid[state.boxy[j]][state.boxx[j]]!= 'T')))
                    {
                        //std::cout<<"Box is Block3"<<state.boxx[i]<<","<<state.boxy[i]<<"--"<<state.boxx[j]<<","<<state.boxy[j]<<std::endl;
                        //std::cout<<"Box: ";
                        //for(int idx = 0; idx < state.boxx.size(); ++idx){
                        //    std::cout<<state.boxx[idx]<<","<<state.boxy[idx]<<std::endl;
                        //}
                        return true;
                    }
                    int downix = state.boxx[i];
                    int downiy = state.boxy[i]+1;
                    int downjx = state.boxx[j];
                    int downjy = state.boxy[j]+1;
                    iIsValid = true;
                    jIsValid = true;
                    if(downix < 0 || downix >= grid[0].size() || downiy < 0 || downiy >= grid.size())
                    {
                        iIsValid = false;
                    }else{
                        if(grid[downiy][downix] == '#')
                        {
                            iIsValid = false;
                        }
                    }
                    if(downjx < 0 || downjx >= grid[0].size() || downjy < 0 || downjy >= grid.size())
                    {
                        jIsValid = false;
                    }else{
                        if(grid[downjy][downjx] == '#')
                        {
                            jIsValid = false;
                        }
                    }
                    if((!iIsValid)&&(!jIsValid)&&((grid[state.boxy[i]][state.boxx[i]]!= 'T')||(grid[state.boxy[j]][state.boxx[j]]!= 'T')))
                    {
                        //std::cout<<"Box is Block3"<<state.boxx[i]<<","<<state.boxy[i]<<"--"<<state.boxx[j]<<","<<state.boxy[j]<<std::endl;
                        //std::cout<<"Box: ";
                        //for(int idx = 0; idx < state.boxx.size(); ++idx){
                        //    std::cout<<state.boxx[idx]<<","<<state.boxy[idx]<<std::endl;
                        //}
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
void LoadLevelFromCharArray(char **pString, int len, std::vector<std::vector<char>>& grid) {
    for (int i = 0; i < len; ++i) {
        std::vector<char> row;
        for (int j = 0; j < strlen(pString[i]); ++j) {
            if (pString[i][j] == '#' || pString[i][j] == '_') {
                row.emplace_back('#');
            }
            if (pString[i][j] == '.') {
                row.emplace_back('T');
            }
            if (pString[i][j] == '-') {
                row.emplace_back('.');
            }
            if (pString[i][j] == '$') {
                row.emplace_back('B');
            }
            if (pString[i][j] == '@') {
                row.emplace_back('S');
            }
        }
        grid.emplace_back(row);
    }
}
char MappingChar(char in)
{
    if(in == '#'||in == '_')
    {
        return ('#');
    }
    if(in == '.')
    {
        return ('T');
    }
    if(in == '-')
    {
        return ('.');
    }
    if(in == '$')
    {
        return ('B');
    }
    if(in == '@')
    {
        return ('S');
    }
    if(in == '*')
    {
        return ('A');
    }
    if(in == '+')
    {
        return ('C');
    }
    return ('N');
}
void LoadLevelsFromFile(const std::string& filename,std::vector<std::vector<std::vector<char>>>& grids, std::vector<std::string>& titles)
{
    std::ifstream infile(filename);
    std::string line;
    int state = 0;
    std::vector<std::vector<char>> grid;
    while(std::getline(infile, line))
    {
        if(state == 0)
        {
            if(line.find(";Level") != std::string::npos)
            {
                state = 1;
                grid.clear();
            }
        }else if(state == 1)
        {
            if(line.find("Title:")!= std::string::npos)
            {
                state = 0;
                grids.emplace_back(grid);
                titles.emplace_back(line.substr(7));
            }else{
                std::vector<char> row;
                for(int i = 0; i < line.size(); ++i)
                {
                    row.emplace_back(MappingChar(line[i]));
                }
                grid.emplace_back(row);
            }
        }
    }
}
void printGame(const std::vector<std::vector<char>>& grid)
{
    for(int i = 0; i < grid.size(); ++i)
    {
        for(int j = 0; j < grid[i].size(); ++j)
        {
            std::cout<<grid[i][j];
        }
        std::cout<<std::endl;
    }
}